package git.soulbgm.common.base;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import tk.mybatis.mapper.autoconfigure.MybatisProperties;

import javax.sql.DataSource;

/**
 * 此类为设置多数据源的抽象类已有实现之需加上
 * - @Bean("bean名称")
 * - @Primary 如果该数据源是主数据源则加此注解
 * 在dataSource方法上加此注解
 * - @ConfigurationProperties(prefix = "数据源的开头")
 * 在class的头部加此注解
 * - @MapperScan(basePackages = "扫描的包", sqlSessionTemplateRef = "SqlSessionTemplate的Bean名称")
 * 有多个数据源时Quartz无法自动分配数据源这时可以使用@QuartzDataSource注解来标记来使用那个数据源
 *
 * @author SoulBGM
 * @version 1.0
 * @date 2019/11/25 14:46
 */
public abstract class BaseDataSourceConfig {

    @Autowired
    private MybatisProperties mybatisProperties;

    /**
     * 通过BeanCopier来克隆从MybatisProperties.getConfiguration()中取出的Configuration对象
     *
     * @return Configuration对象
     */
    protected org.apache.ibatis.session.Configuration getNewConfiguration() {
        org.apache.ibatis.session.Configuration conf = mybatisProperties.getConfiguration();
        org.apache.ibatis.session.Configuration newConf = new org.apache.ibatis.session.Configuration();
        BeanCopier copier = BeanCopier.create(conf.getClass(), newConf.getClass(), false);
        copier.copy(conf, newConf, null);
        return newConf;
    }

    /**
     * 获取解析映射器位置
     *
     * @return Resource数组
     */
    protected Resource[] getResolveMapperLocations() {
        return mybatisProperties.resolveMapperLocations();
    }

    protected DataSource dataSource;

    protected SqlSessionFactory sqlSessionFactory;

    protected DataSourceTransactionManager dataSourceTransactionManager;

    protected SqlSessionTemplate sqlSessionTemplate;

    /*@Bean("primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.primary")*/
    public DataSource dataSource() {
        return dataSource = DruidDataSourceBuilder.create().build();
    }

    /*@Bean("primarySqlSessionFactory")
    @Primary*/
    public SqlSessionFactory sqlSessionFactory() {
        if (dataSource == null) {
            dataSource();
        }
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        // 沿用配置文件中的mybatis的配置
        bean.setMapperLocations(getResolveMapperLocations());
        bean.setConfiguration(getNewConfiguration());
        try {
            return sqlSessionFactory = bean.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /*@Bean("primaryTransactionManager")
    @Primary*/
    public DataSourceTransactionManager transactionManager() {
        if (dataSource == null) {
            dataSource();
        }
        return dataSourceTransactionManager = new DataSourceTransactionManager(dataSource);
    }

    /*@Bean("primarySqlSessionTemplate")
    @Primary*/
    public SqlSessionTemplate sqlSessionTemplate() {
        if (sqlSessionFactory == null) {
            sqlSessionFactory();
        }
        return sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
    }


}
